/* 
 * File:   JServer.cpp
 * Author: johnneyshi
 * 
 * Created on 2013年1月26日, 下午1:10
 */

#include "JServer.h"
#include <sys/socket.h>
#include <sys/epoll.h>
#include <string.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include "JException.h"
#include "JLog.h"
#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include "JBuffer.h"
#include "JException.h"
#include "JLog.h"
using namespace std;


JServer::JServer() 
{
}

JServer::JServer(std::string _ip, int _port) : ip(_ip),port(_port)
{
    
}

//JServer::JServer(const JServer& orig) 
//{
//    
//}

void JServer::Init(std::string _ip, int _port)
{
    this->ip = _ip;
    this->port = _port;
}

JServer::~JServer() {
}

std::string JServer::GetIP()
{
    return this->ip;
}

int JServer::GetPort()
{
    return this->port;
}

void JServer::Start()
{
    int listenFd = Bind(this->ip,this->port);
    //std::cout << "bind success:" << listenFd << std::endl;
    Wait(listenFd);
    while(true)
    {
        sleep(30000);
    }
}

int JServer::Bind(std::string _ip,int _port)
{
    struct sockaddr_in serverAddr;
    bzero(&serverAddr,sizeof(sockaddr_in));
    
    int listenFd = socket(AF_INET,SOCK_STREAM,0);
    if(listenFd < -1)
    {
        throw JException("JServer::Bind listenFd error.");
    }
    SetNonBlock(listenFd);
    serverAddr.sin_family = AF_INET;
    inet_aton(_ip.c_str(),&serverAddr.sin_addr);
    serverAddr.sin_port = htons(_port);
    if(bind(listenFd,(struct sockaddr*)&serverAddr,sizeof(sockaddr_in)) < 0)
    {
        throw JException("ScheduleServer::Bind bind error.");
    }
    if(listen(listenFd,5) < 0)
    {
        throw JException("ScheduleServer::Bind listen error.");
    }
    return listenFd;
}

void JServer::SetNonBlock(int fd)
{
    if(fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK) == -1)
    {
        
    }
}


void JServer::Wait(int fd)
{
    struct sockaddr_in clientAddr;
    bzero(&clientAddr,sizeof(sockaddr_in));
    socklen_t clientSocketLength = sizeof(sockaddr_in);
    
    struct epoll_event ev;
    struct epoll_event allEvent[200];
    
    epollHandler = epoll_create(200);
    ev.events = EPOLLIN | EPOLLET;
    ev.data.fd = fd;
    if(epoll_ctl(epollHandler,EPOLL_CTL_ADD,fd,&ev) < 0)
    {
        throw JException("JServer::Wait epoll_ctl error.");
    }
    while(true)
    {
        //cout << "hello" << endl;
        int maxCount = 200;
        int eventCount = epoll_wait(epollHandler,allEvent,maxCount,-1);
        JLog::Log(JLogMessage,"epoll_wait wait something.");
        //cout << "wait guo" << endl;
        if(eventCount == -1)
        {
            throw JException("JServer::Wait epoll_wait error.");
        }
        for(int i = 0;i < eventCount; ++i)
        {
            JLog::Log(JLogMessage,"Event fd: %d",allEvent[i].data.fd);
            //cout << "event:" << allEvent[i].data.fd << endl;
            int newFd;
            //New connection come.
            if(allEvent[i].data.fd == fd)
            {
                newFd = accept(fd,(struct sockaddr*)&clientAddr,&clientSocketLength);
                if(newFd < 0)
                {
                    throw JException("JServer::Wait accept error.");
                }
                else
                {
                    DealNewConnfd(newFd);
//                    char buff[200];
//                    sprintf(buff,"new connection come: fd %d",newFd);
//                    SetNonBlock(newFd);
//                    ev.events = EPOLLIN | EPOLLET;
//                    ev.data.fd = newFd;
//                    if(epoll_ctl(epollHandler,EPOLL_CTL_ADD,newFd,&ev) < 0)
//                    {
//                        throw JException("JServer::Wait epoll_ctl error.");
//                    }
                }
            }
            else
            {
                
                DealEpollFd(allEvent[i].data.fd);
            }
        }
    }
}

void JServer::DealEpollFd(int fd)
{
    cout << "HandleMessage" << endl;
    char buff[1024];
    int n = 0;
    while(true)
    {
        bzero(buff,1024);
        //cout << "hello" << endl;
        n = read(fd,buff,1024);
        //cout << "world" << endl;
        if(n <= 0)
        {
            break;
        }
        cout << "Receive message:" << buff;
    }
}

JBuffer* JServer::GetAvailableBuffer()
{
    for(int i = 0;i < this->pBuffers.size(); ++i)
    {
        if(this->pBuffers[i]->IsInUsed() == false)
        {
            this->pBuffers[i]->SetInUsed();
            return this->pBuffers[i];
        }
    }
    JBuffer* buff = new JBuffer;
    this->pBuffers.push_back(buff);
    return this->pBuffers[this->pBuffers.size() - 1];
}

void JServer::DealNewConnfd(int newFd)
{
//     char buff[200];
//                    sprintf(buff,"new connection come: fd %d",newFd);
//                    SetNonBlock(newFd);
//                    ev.events = EPOLLIN | EPOLLET;
//                    ev.data.fd = newFd;
//                    if(epoll_ctl(epollHandler,EPOLL_CTL_ADD,newFd,&ev) < 0)
//                    {
//                        throw JException("JServer::Wait epoll_ctl error.");
//                    }
}